package com.sky.service.impl;

import cn.hutool.json.JSONUtil;
import cn.hutool.poi.word.WordUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sky.constant.MessageConstant;
import com.sky.dto.CompetitionApplicationDTO;
import com.sky.dto.TeacherInfoDTO;
import com.sky.dto.common.PageRequest;
import com.sky.dto.common.QueryParams;
import com.sky.entity.*;
import com.sky.exception.CommonException;
import com.sky.mapper.CompetitionMapper;
import com.sky.mapper.CompetitionApplicationMapper;
import com.sky.mapper.FileListMapper;
import com.sky.mapper.InstructorMapeer;
import com.sky.result.PageResult;
import com.sky.service.CompetitionService;
import com.sky.utils.AliOssUtil;
import com.sky.utils.QcloudUtil;
import com.sky.vo.CompetionListQueryVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.UUID;

@Service
@Slf4j
public class CompetitionServiceImpl implements CompetitionService {
    @Autowired
    private AliOssUtil aliOssUtil;
    @Autowired
    private CompetitionMapper competitionMapper;
    @Autowired
    private CompetitionApplicationMapper competitionApplicationMapper;
    @Autowired
    private InstructorMapeer instructorMapeer;
    @Autowired
    private FileListMapper fIleListMapper;
    @Autowired
    private QcloudUtil qcloudUtil;

    @Override
    @Transactional
    public void save(CompetitionApplicationDTO competitionAddDTO)  {
        // 获取个人信息
        Instructor infoById = instructorMapeer.getInfoById(competitionAddDTO.getInstructorId());
        if (infoById == null || "1".equals(infoById.getStatus())) {
            throw new CommonException(MessageConstant.COMPETITION_NUMBER_EORROR);
        }
        // 1. 保存竞赛基本信息
        Competition competition = new Competition();
        BeanUtils.copyProperties(competitionAddDTO, competition);
        // 处理教师信息等
        String teacherInfo = JSONUtil.toJsonStr(competitionAddDTO.getTeacher());
        competition.setTeacher(teacherInfo);
        competitionMapper.insert(competition);
        // 处理竞赛附件信息
        List<FileList> fileLists = competitionAddDTO.getFileLists();
        if(fileLists != null && fileLists.size() > 0){
            for (FileList fileList : fileLists) {
                fileList.setKeyId(competition.getId());
                fIleListMapper.insert(fileList);
            }
        }
        // 2. 开始处理竞赛申请表同步创建
        // 生成word表格并存入resources/File/temp目录
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        String timestamp = LocalDateTime.now().format(formatter);
        String outputFileName = competition.getContact()+ "_大学生竞赛申请表" +timestamp + ".docx";
        // 获取竞赛表中的数量
        int size = competitionAddDTO.getTeacher().size()-2;
// 动态构建模板文件路径
        String templatePath = "File/大学生竞赛（校外）申请表_" + size + ".docx";
        // 生成Word文档，返回相对路径
//        String documentRelativePath = WordDocumentUtil.generateDocumentForStorage(templatePath, competitionAddDTO, outputFileName);
        String documentRelativePath = createWord(competitionAddDTO,outputFileName,templatePath);

        // 将相对路径转换为完整的文件系统路径
        String resourcesPath = this.getClass().getClassLoader().getResource("").getPath();
        String documentFullPath = resourcesPath + documentRelativePath;

        // 调用腾讯云cos上传文件，返回URL
        String documentUrl = null;
        String cosKey = competitionAddDTO.getContact()+competitionAddDTO.getInstructorId();
//            documentUrl = aliOssUtil.uploadFile(documentFullPath, outputFileName);
        documentUrl = qcloudUtil.uploadFile(documentFullPath, outputFileName,cosKey);
        // 创建对应的竞赛申请表信息
        CompetitionApplication application = CompetitionApplication.builder()
                .competitionId(competition.getId())
                .instructorId(competitionAddDTO.getInstructorId())
                .fileList(documentUrl)
                .isPublished(0)
                .isSubmit(0)
                .contact(competitionAddDTO.getContact())
                .departmentId(infoById.getDepartmentId())
                .applicationStatus(0)
                .currentReviewLevel(2)
                .categoryId(competitionAddDTO.getCategoryId())
        .build();
        competitionApplicationMapper.insert(application);
        // 删除临时文件 - 使用完整路径
        boolean deleted = deleteTempFile(documentFullPath);
        if (!deleted) {
            log.warn("临时文件删除失败，但不影响业务流程: {}", documentFullPath);
        }
    }

    @Override
    public void deleteById(String id) {

    }

    @Override
    public void update(CompetitionApplicationDTO competitionUpdateDTO) {

    }

    @Override
    public CompetitionApplicationDTO getById(String id) {
        Competition byId = competitionMapper.getById(id);
        CompetitionApplicationDTO result = new CompetitionApplicationDTO();
        BeanUtils.copyProperties(byId, result);
        // 处理教师信息转为对象
        List<TeacherInfoDTO> list = JSONUtil.toList(byId.getTeacher(), TeacherInfoDTO.class);
        // 获取附件信息
        List<FileList> fileListByCompetitionId = fIleListMapper.getFileListByCompetitionId(id);
        result.setTeacher(list);
        result.setFileLists(fileListByCompetitionId);
        return result;
    }

    @Override
    public String generateApplicationDocument(String id) {
        return "";
    }

    @Override
    public PageResult pageQuery(PageRequest<QueryParams> queryParams) {
        PageHelper.startPage(queryParams.getPageNum(), queryParams.getPageSize());
        List<CompetionListQueryVO> competitionList = competitionApplicationMapper.pageQuery(queryParams.getParams());
        PageInfo<CompetionListQueryVO> pageInfo = new PageInfo<>(competitionList);

        // 为每个竞赛查询附件信息
        for (CompetionListQueryVO competition : competitionList) {
            List<FileList> fileListByCompetitionId = fIleListMapper.getFileListByCompetitionId(competition.getCompetitionId());
            competition.setFileLists(fileListByCompetitionId);
        }

        return new PageResult(pageInfo.getTotal(), pageInfo.getList());
    }

    //-================================  专用 方法 =================================

    /**
     * 创建临时文件
     * @param competitionAddDTO 竞赛信息
     * @param outputFileName  输出文件名
     * @param templatePath 模板路径
     * @return 临时文件相对路径
     */
    public static String createWord(CompetitionApplicationDTO competitionAddDTO,String outputFileName,String templatePath) {
        String relativePath = ""; // 返回的临时文件路径
        // 1. 读取 resources 目录下的模板文件
        InputStream fis = WordUtil.class.getClassLoader().getResourceAsStream(templatePath);
        if (fis == null) {
            throw new RuntimeException("模板文件不存在！");
        }
        // 生成word表格
        try (XWPFDocument document = new XWPFDocument(fis)) {
            XWPFTable table = document.getTables().get(0);
            table.getRow(0).getCell(1).setText(competitionAddDTO.getName());
            table.getRow(1).getCell(1).setText(competitionAddDTO.getConductUnit());
            table.getRow(1).getCell(3).setText(competitionAddDTO.getScope());
            table.getRow(2).getCell(1).setText(competitionAddDTO.getOrganizer());
            table.getRow(2).getCell(3).setText(competitionAddDTO.getLevel());
            table.getRow(3).getCell(1).setText(competitionAddDTO.getShape());
            table.getRow(3).getCell(3).setText(competitionAddDTO.getTraffic());
            table.getRow(4).getCell(1).setText(competitionAddDTO.getType());
            table.getRow(4).getCell(3).setText(competitionAddDTO.getNumber().toString());
            table.getRow(5).getCell(1).setText(competitionAddDTO.getAddress());

            // 格式化时间，去掉T
            DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            table.getRow(5).getCell(3).setText(competitionAddDTO.getStartTime().format(timeFormatter));

            table.getRow(6).getCell(1).setText(competitionAddDTO.getContact());
            table.getRow(6).getCell(3).setText(competitionAddDTO.getPhone());
            // 填写指导教师信息 - 使用动态扩展功能
            List<TeacherInfoDTO> teacherList = competitionAddDTO.getTeacher(); // 假设这是教师列表
            int teacherStartRow = 8; // 教师信息开始行
            // 2. 填充教师信息
            for (int i = 0; i < teacherList.size(); i++) {
                XWPFTableRow row = table.getRow(teacherStartRow + i);
                TeacherInfoDTO teacher = teacherList.get(i);
                row.getCell(1).setText(teacher.getName()); //姓名
                row.getCell(2).setText(teacher.getEducation()); // 学历
                row.getCell(3).setText(teacher.getTitle()); //职称
                row.getCell(4).setText(teacher.getDepartment()); // 部门
                row.getCell(5).setText(teacher.getRemarks()); // 备注
            }
            // 新的索引行数
            int newTeacherRows = teacherList.size()+ teacherStartRow;
            // 竞赛实施方案
            XWPFTableRow row = table.getRow(newTeacherRows);
            XWPFTableCell cell = row.getCell(1);
            while (cell.getParagraphs().size() > 0) {
                cell.removeParagraph(0);
            }
            String[] lines = competitionAddDTO.getPlan().split("\\r?\\n"); // 直接分割而不用方法
            for (String line : lines) {
                XWPFParagraph paragraph = cell.addParagraph();
                XWPFRun run = paragraph.createRun();
                run.setText(line);
                paragraph.setSpacingBetween(1.5);
            }
            // 上届竞赛经费获奖情况
            table.getRow(newTeacherRows+1).getCell(1).setText(competitionAddDTO.getCost());
            // 经费预算
            XWPFTableRow row2 = table.getRow(newTeacherRows+2);
            XWPFTableCell cell2 = row2.getCell(1);
            while (cell2.getParagraphs().size() > 0) {
                cell2.removeParagraph(0);
            }
            String[] lines2 = competitionAddDTO.getBudget().split("\\r?\\n"); // 直接分割而不用方法
            for (String line : lines2) {
                XWPFParagraph paragraph = cell2.addParagraph();
                XWPFRun run2 = paragraph.createRun();
                run2.setText(line);
                paragraph.setSpacingBetween(1.5);
            }
            // 开始写入临时文件
            try {
                String tempFilePath = createTempFile(document, outputFileName);
                document.close();
                fis.close();
                // 返回相对路径（用于存储到数据库）
                 relativePath = "File/temp/" + new File(tempFilePath).getName();
                log.info("Word文档生成成功，相对路径: {}", relativePath);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return relativePath;
    }

    /**
     * 创建临时文件到指定目录
     */
    private static String createTempFile(XWPFDocument document, String fileName) throws Exception {
        // 生成唯一的文件名
        String uniqueFileName = UUID.randomUUID().toString() + "_" + fileName;
        // 使用resources/File/temp目录作为临时文件存储位置
        String tempDir = getResourcesTempDir();
        log.info("获取到临时文件路径是！{}",tempDir);
        String tempFilePath = tempDir + File.separator + uniqueFileName;
        // 确保目录存在
        File directory = new File(tempDir);
        if (!directory.exists()) {
            directory.mkdirs();
        }
        // 写入文件
        try (FileOutputStream out = new FileOutputStream(tempFilePath)) {
            document.write(out);
        }
        return tempFilePath;
    }

    /**
     * 获取resources/File/temp目录路径
     */
    private static String getResourcesTempDir() {
        try {
            // 获取resources目录路径
            ClassPathResource resource = new ClassPathResource("");
            String resourcesPath = resource.getFile().getPath();
            return resourcesPath + File.separator + "File" + File.separator + "temp";
        } catch (Exception e) {
            // 如果获取resources路径失败，使用项目根目录下的temp
            return System.getProperty("user.dir") + File.separator + "temp";
        }
    }
    /**
     * 删除临时文件
     */
    public static boolean deleteTempFile(String tempFilePath) {
        try {
            File file = new File(tempFilePath);
            if (file.exists()) {
                boolean deleted = file.delete();
                return deleted;
            } else {
                return false;
            }
        } catch (Exception e) {
            log.error("删除临时文件失败: {}", tempFilePath, e);
            return false;
        }
    }
}
